﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using BLL;
using DAL;

namespace SL
{
    [ServiceBehavior(
        ConcurrencyMode = ConcurrencyMode.Single,
        InstanceContextMode = InstanceContextMode.PerCall)]
    public class RemoteService : IRemoteService
    {
        // List of subscribing clients
        private static IDictionary<int, List<IRemoteServiceCallback>> subscribers = new Dictionary<int, List<IRemoteServiceCallback>>();

        # region booking

        static BookingCTR _bookingCtr = new BookingCTR();

        public void SaveBooking(Booking booking)
        {
            _bookingCtr.SaveBooking(booking);
        }

        # endregion

        # region seat

        static SeatCTR _seatCtr = new SeatCTR();

        public IList<ScreenCast_Seat> GetBestSeats(List<ScreenCast_Seat> screenSeatList, int neededSeats, ScreenCast_Seat clickedSeat)
        {
            return _seatCtr.GetBestSeats(screenSeatList, neededSeats, clickedSeat);
        }

        public void ChangeSeatsAvailability(List<ScreenCast_Seat> screenSeats)
        {
            _seatCtr.ChangeSeatsAvailability(screenSeats);

            // remove clients which have a closed connection
            subscribers[screenSeats.First().ScreenCastId].RemoveAll(s => ((ICommunicationObject)s).State == CommunicationState.Closed);

            // Notify each listening client!
            foreach (IRemoteServiceCallback cb in subscribers[screenSeats.First().ScreenCastId])
            {
                // Call callback method
                cb.OnAction(screenSeats);
            }

        }

        public IList<ScreenCast_Seat> GetScreenCastSeats(ScreenCast screenCast)
        {
            return _seatCtr.GetScreenCastSeats(screenCast);
        }

        public IList<Seat> GetSeats(MovieHall movieHall)
        {
            return _seatCtr.GetSeats(movieHall);
        }

        # endregion

        # region cinema

        static CinemaCTR _cinemaCtr = new CinemaCTR();

        public IList<Cinema> GetCinemas()
        {
            return _cinemaCtr.GetCinemas();
        }

        # endregion

        # region movie hall

        static MovieHallCTR _movieHallCtr = new MovieHallCTR();

        public MovieHall GetMovieHall(int id)
        {
            return _movieHallCtr.GetMovieHall(id);
        }


        public IList<MovieHall> GetMovieHalls(Cinema cinema)
        {
            return _movieHallCtr.GetMovieHalls(cinema);
        }

        public MovieHall GetMovieHall(ScreenCast screenCast)
        {
            return _movieHallCtr.GetMovieHall(screenCast);
        }

        # endregion

        # region movie

        static MovieCTR _movieCtr = new MovieCTR();

        public IList<Movie> GetMovies(Cinema cinema)
        {
            return _movieCtr.GetMovies(cinema);
        }

        public IList<Movie> SearchIMDBMovies(string title)
        {
            return _movieCtr.SearchIMDBMovies(title);
        }

        public void AddMovie(Movie movie)
        {
            _movieCtr.AddMovie(movie);
        }

        # endregion

        # region screen cast

        static ScreenCastCTR _screenCastCtr = new ScreenCastCTR();

        public ScreenCast GetScreenCast(int id)
        {
            return _screenCastCtr.GetScreenCast(id);
        }

        public IList<ScreenCast> GetScreenCasts(Movie movie, Cinema cinema)
        {
            return _screenCastCtr.GetScreenCasts(movie, cinema);
        }

        public void AddScreenCast(ScreenCast screenCast)
        {
            _screenCastCtr.AddScreenCast(screenCast);
        }

        # endregion

        # region user

        static UserCTR _userCtr = new UserCTR();

        public User GetCustomer(string phoneNo)
        {
            return _userCtr.GetCustomer(phoneNo);
        }

        public bool IsEmployeeAllowed(string initials)
        {
            return _userCtr.IsEmployeeAuthorized(initials);
        }

        # endregion

        #region callback

        public bool Subscribe(ScreenCast screenCast)
        {
            try
            {
                IRemoteServiceCallback callback = OperationContext.Current.GetCallbackChannel<IRemoteServiceCallback>();
                if (!subscribers.Keys.Contains(screenCast.Id)) // if key does not exist, add it
                {
                    subscribers.Add(screenCast.Id, new List<IRemoteServiceCallback>());
                }
                if (!subscribers[screenCast.Id].Contains(callback)) // if value under key does not exist, add it
                {
                    subscribers[screenCast.Id].Add(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Unsubscribe(ScreenCast screenCast)
        {
            try
            {
                IRemoteServiceCallback callback = OperationContext.Current.GetCallbackChannel<IRemoteServiceCallback>();
                if (subscribers[screenCast.Id].Contains(callback))
                {
                    subscribers[screenCast.Id].Remove(callback);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion
    }
}
